package solutions.ferpa.ztest.intf;

import br.com.telescope.adsrt.dom.DomDate;
import br.com.telescope.adsrt.dom.DomEMail;
import br.com.telescope.adsrt.dom.DomFlag;
import br.com.telescope.adsrt.dom.DomId;
import br.com.telescope.adsrt.dom.DomLogin;
import br.com.telescope.adsrt.dom.DomPasswordHash;
import br.com.telescope.adsrt.dom.DomTextLong;
import br.com.telescope.adsrt.dom.DomUpper;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.t2.AccessPolicy;
import br.com.telescope.t2.ContextNavigator;
import br.com.telescope.t2.ServiceModel;
import br.com.telescope.t2.config.Config;
import br.com.telescope.t2.exception.ApplicationRuntimeException;
import br.com.telescope.t2.feature.AbstractFeature;
import br.com.telescope.t2.feature.CustomFeature;
import br.com.telescope.t2.feature.InsertFeature;
import br.com.telescope.util.StringReplacer;
import br.com.telescope.util.URLParameters;
import java.util.UUID;
import solutions.ferpa.ztest.ent.*;
import solutions.ferpa.ztest.intf.*;

/**
 * Cadastre-se para usar o sistema.
 * <p>
 * Interface pública para registro de usuários e chave de ativação.
 * <P>
 * Quando o usuário fizer o seu cadastro, será gerada uma chave de 
 * ativação que deverá ser confirmada (link no email).
 * <P>
 * O cadastramento do usuário também recebe acesso para algumas funções 
 * conforme definido na propriedade [t:#3822218]
 * <P>
 * 
 * <P>
 * Telescope origin: RTAUTH.CRIA_CONTA
 * <P>
 * Base entity: RTAUTH.USUARIOS
 * <P>
 * @author TELESCOPE - Build task T2 Web Interface Generator
 * <P>
 * @version 0.1
 */
public class CriaConta extends ServiceModel {
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public static final String GLOBAL_NAME = "RTAUTH.CRIA_CONTA";
    
    @Override
    public String globalName() {
        return GLOBAL_NAME;
    }
    
    {
        setTitle("Cadastre-se para usar o sistema");
    }
    
    protected EntUsuarios base;
    protected EntUsuarios rec; // NEED_TJW1_COMPATIBILITY
    
    // Record items
    private DomUpper aNomeCompleto;
    private DomEMail aEMail;
    private DomPasswordHash aSenhaHash;
    private DomFlag aAtivo;
    private DomId aId;
    private DomLogin aLogin;
    private DomId aMenuId;
    private DomId aPessoaId;
    private DomFlag aSuperUsuario;
    private DomDate aValidade;
    private DomPasswordHash aConfirmacaoSenha;
    private DomTextLong aInstrucoes;
    
    // Query items
    
    @Override
    public void copyDefaultValues() {
        copyDefaultValue(base.getAtivo(), aAtivo);
    }
    
    @Override
    public String getBaseSql() {
        return "select BASE.*"
                + " from USUARIOS BASE";
    }
    
    @Override
    public void initAttributes() {
        
        aNomeCompleto = new DomUpper();
        aNomeCompleto.context(ctx).name("NOME_COMPLETO").label("Nome completo");
        
        aEMail = new DomEMail();
        aEMail.context(ctx).name("E_MAIL").label("E-Mail");
        
        aSenhaHash = new DomPasswordHash();
        aSenhaHash.context(ctx).name("SENHA_HASH").label("Senha").width(12);
        
        aAtivo = new DomFlag();
        aAtivo.context(ctx).name("ATIVO").label("Ativo");
        aAtivo.setDefaultValue("N");
        
        aId = new DomId();
        aId.context(ctx).name("ID").label("ID");
        
        aLogin = new DomLogin();
        aLogin.context(ctx).name("LOGIN").label("Login");
        
        aMenuId = new DomId();
        aMenuId.context(ctx).name("MENU_ID").label("Menu inicial");
        
        aPessoaId = new DomId();
        aPessoaId.context(ctx).name("PESSOA_ID").label("Pessoa");
        
        aSuperUsuario = new DomFlag();
        aSuperUsuario.context(ctx).name("SUPER_USUARIO").label("Super usuário");
        aSuperUsuario.setDefaultValue("N");
        
        aValidade = new DomDate();
        aValidade.context(ctx).name("VALIDADE").label("Validade");
        
        aConfirmacaoSenha = new DomPasswordHash();
        aConfirmacaoSenha.context(ctx).name("CONFIRMACAO_SENHA").label("Repetir senha").width(12).unbound(true);
        
        aInstrucoes = new DomTextLong();
        aInstrucoes.context(ctx).name("INSTRUCOES").label("Instruções").unbound(true);
        
    }
    
    @Override
    public String getQueryPkColumn() {
        return "BASE.ID";
    }
    
    @Override
    public void setId(String value) {
        this.aId.setValue(value);
    }
    
    @Override
    public EntUsuarios getRecord() {
        if (base == null) {
            base = new EntUsuarios(ctx);
            rec = base;
        }
        return this.base;
    }
    
    @Override
    public String getDefaultOrderBy() {
        return "";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="INSERT">
    public class FInsert extends InsertFeature {
        
        @Override
        public void initForm() {
            aNomeCompleto.setOptional(false);
            addField(aNomeCompleto, "rqd");
            aEMail.setOptional(false);
            addField(aEMail, "rqd");
            aSenhaHash.setOptional(false);
            addField(aSenhaHash, "rqd");
            aConfirmacaoSenha.setOptional(false);
            addField(aConfirmacaoSenha, "rqd");
        }
        
        @Override
        public int getAccessPolicy() {
            return AccessPolicy.PUBLIC;
        }
        
        @Override
        public void posInsert() {
            try {
                adicionarChaveAtivacao();
                {
                    CriaConta external = new CriaConta();
                    external.setRuntime(ctx);
                    external.init();
                    ContextNavigator cn = updatedContextNavigator();
                    if (cn != null) {
                        cn.getLastModule().setActive(external);
                        ctx.setParameter("Z_CN", cn.toText());
                    }
                    AbstractFeature feature = external.getFeature("SUCCESS");
                    external.setCurrentFeature(feature);
                    setNextFeature(feature, "");
                }
                criarPerfil();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void preInsert() {
            try {
                conferirDadosDigitados();
                setLoginValue();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("INSERT");
            setTitle(" ");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="SUCCESS">
    public class FSuccess extends CustomFeature {
        
        @Override
        public void initForm() {
        }
        
        @Override
        public int getAccessPolicy() {
            return AccessPolicy.PUBLIC;
        }
        
        @Override
        public void preDisplay() {
            try {
                showSuccessMessage();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("SUCCESS");
            setTitle("Conta criada com sucesso");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="initFeatures">
    
    @Override
    protected void initFeatures() {
        addFeature(new FInsert());
        addFeature(new FSuccess());
        super.initFeatures();
    }
    
    @Override
    public String getDefaultFeature() {
        return "INSERT";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    public String getNomeCompleto() {
        return aNomeCompleto.getValue();
    }
    
    public void setNomeCompleto(String value) {
        this.aNomeCompleto.setValue(value);
    }
    
    public String getEMail() {
        return aEMail.getValue();
    }
    
    public void setEMail(String value) {
        this.aEMail.setValue(value);
    }
    
    public String getSenhaHash() {
        return aSenhaHash.getValue();
    }
    
    public void setSenhaHash(String value) {
        this.aSenhaHash.setValue(value);
    }
    
    public String getAtivo() {
        return aAtivo.getValue();
    }
    
    public void setAtivo(String value) {
        this.aAtivo.setValue(value);
    }
    
    @Override
    public Long getId() {
        return aId.getValue();
    }
    
    public void setId(Long value) {
        this.aId.setValue(value);
    }
    
    public String getLogin() {
        return aLogin.getValue();
    }
    
    public void setLogin(String value) {
        this.aLogin.setValue(value);
    }
    
    public Long getMenuId() {
        return aMenuId.getValue();
    }
    
    public void setMenuId(Long value) {
        this.aMenuId.setValue(value);
    }
    
    public Long getPessoaId() {
        return aPessoaId.getValue();
    }
    
    public void setPessoaId(Long value) {
        this.aPessoaId.setValue(value);
    }
    
    public String getSuperUsuario() {
        return aSuperUsuario.getValue();
    }
    
    public void setSuperUsuario(String value) {
        this.aSuperUsuario.setValue(value);
    }
    
    public java.sql.Date getValidade() {
        return aValidade.getValue();
    }
    
    public void setValidade(java.sql.Date value) {
        this.aValidade.setValue(value);
    }
    
    public String getConfirmacaoSenha() {
        return aConfirmacaoSenha.getValue();
    }
    
    public void setConfirmacaoSenha(String value) {
        this.aConfirmacaoSenha.setValue(value);
    }
    
    public String getInstrucoes() {
        return aInstrucoes.getValue();
    }
    
    public void setInstrucoes(String value) {
        this.aInstrucoes.setValue(value);
    }
    // </editor-fold>
    
    /**
     * Criar perfil do usuário.
     * <p>
     * Monta um perfil de acesso padrão para o usuário, incluindo todas as 
     * funções de acesso definidas na preferencia [t:#3822217].
     * <P>
     */
    public void criarPerfil() throws AdsException {
        // <user-code id="3822225" parentId="3822221" hashcode="404213fd" length="558">
        // import br.com.telescope.t2.config.Config;
        
        EntFuncoesSistemas funcao = new EntFuncoesSistemas(ctx);
        String roles = Config.getInstance().getParameter(globalName("USER_FUNCTIONS"), "").trim();
        if (roles.isEmpty()) return;
        for (String role : roles.split("\n")) {
            role = role.trim();
            if (!role.isEmpty()) {
                funcao.findByFuncaoSistema(role);
                EntFuncoesUsuarios fusi = new EntFuncoesUsuarios(ctx);
                fusi.setFuncaoId(funcao.valueOfId());
                fusi.setUsuarioId(getRecord().valueOfId());
                fusi.ins();
            }
        }
        // </user-code>
    }
    
    /**
     * Adicionar chave de ativação.
     * <p>
     * Quando o usuário for cadastrado vai ser gerado uma chave de ativação e 
     * enviado um E-Mail para confirmar o cadastro
     */
    private void adicionarChaveAtivacao() throws AdsException {
        // <user-code id="799519" parentId="799515" hashcode="2e819aa1" length="1416">
        // import java.util.UUID;
        // import br.com.telescope.util.StringReplacer;
        // import br.com.telescope.util.URLParameters;
        EntChavesAtivacao chavesAtivacao = new EntChavesAtivacao(ctx);
        chavesAtivacao.setChaveAtivacao(UUID.randomUUID());
        chavesAtivacao.setUsuarioId(getRecord().valueOfId());
        chavesAtivacao.setServico("RTAUTH.ATIVAR_CONTA");
        chavesAtivacao.save();
        
        StringBuilder email = new StringBuilder(2000);
        
        email.append("Olá ${NOME_COMPLETO}<br /><br />"
                + "${EMAIL}<br /><br />"
                + "Bem vindo!<br /><br />"
                + "Clique no link abaixo para confirmar seu email e ativar sua conta<br />"
                + "<a href=\"${URL}\">clique aqui!</a><br /><br />"
                + "O seu usuário será ativado somente se você clicar neste link confirmando a ativaçãa de sua conta");
        
        URLParameters params = (new URLParameters()).put("P_HASH", chavesAtivacao.getChaveAtivacao());
        String url = ctx.getServiceUrl("ATIVAR_CONTA", params);
        
        String message = (new StringReplacer(ctx.getPreference("RTAUTH.CRIA_CONTA.CONFIRM_EMAIL_BODY", email.toString())))
                .params("NOME_COMPLETO", aNomeCompleto.getValue())
                .params("EMAIL", aEMail.getValue())
                .params("URL", url)
                .toString();
        
        ctx.sendHtmlMail(aEMail.getValue(), null, ctx.getPreference("RTAUTH.CRIA_CONTA.CONFIRM_EMAIL_SUBJECT", "Confirmação de conta"), message);
        
        getCurrentFeature().setSuccessMessage("");
        
        // </user-code>
    }
    
    /**
     * Conferir dados digitados.
     * <p>
     * Conferir se os dados digitados estão ok e apresentar mensagem 
     * apropriada para o usuário.
     */
    private void conferirDadosDigitados() throws AdsException {
        // <user-code id="792942" parentId="792940" hashcode="21c2adf6" length="531">
        EntUsuarios usuario = new EntUsuarios(ctx);
        if (!aSenhaHash.getValue().equals(aConfirmacaoSenha.getValue())) {
            throw new AdsException(GLOBAL_NAME + ".PASSWORDS_NOT_EQUALS", AdsException.ERROR, "A confirmação de senha não confere com a senha!");
        } else {
            usuario.filterBy().equal(usuario.getEMail(), aEMail.getValue());
            if (usuario.next()) {
                throw new AdsException(GLOBAL_NAME + ".EMAIL_ALREADY_EXISTS", AdsException.ERROR, "Usuário já cadastrado no sistema! Informe outro usuário para login.");
            }
        }
        
        // </user-code>
    }
    
    /**
     * Preencher as instruções de cadastro.
     * <p>
     * Listar as instruções de cadastro do usuário e explicações do processo 
     * de confirmação deste cadastro.
     */
    private void preencherInstrucoesCadastro() throws AdsException {
        // <user-code id="806831" parentId="792776" hashcode="-5c14fb1b" length="422">
        StringBuilder msg = new StringBuilder();
        msg.append(
                ctx.getPreference("RTAUTH.MENSAGEM_CRIAR_CONTA",
                "Caso você já tenha uma conta registrada e ativa. Clique no link abaixo para fazer o login:"
                + "\n"
                + "blalbalall"
                + "\n"
                + "Obs.: Alterar estes texto na preferência RTAUTH.MENSAGEM_CRIAR_CONTA."
                + "\n")
                );
        
        aInstrucoes.setValue(msg.toString());
        // </user-code>
    }
    
    /**
     * Preencher as instruções de confirmação.
     * <p>
     * Listar as instruções para o usuário de como proceder para confirmar o 
     * seu cadastro.
     */
    private void preencherInstrucoesConfirmacao() throws AdsException {
        // <user-code id="806832" parentId="792778" hashcode="-451c4046" length="441">
        StringBuilder msg = new StringBuilder();
        msg.append(
                ctx.getPreference("RTAUTH.MENSAGEM_AGUARDANDO_CONFIRMACAO_CONTA",
                "Parabéns, o seu usuário foi cadastrado com sucesso."
                + "\n"
                + "Você receberá no seu email um link para confirmação e ativação do seu usuário no Telescope."
                + "\n"
                + "Aguardamos a sua confirmação."
                + "\n")
                );
        
        aInstrucoes.setValue(msg.toString());
        // </user-code>
    }
    
    /**
     * Set login value.
     * <p>
     * Seta o login com o mesmo valor do email
     */
    private void setLoginValue() throws AdsException {
        // <user-code id="799553" parentId="799549" hashcode="28b20686" length="40">
        getRecord().setLogin(aEMail.getValue());
        // </user-code>
    }
    
    /**
     * Show success message.
     * <p>
     * Cria mensagem de sucesso na criação de conta com informações para 
     * confirmar sua conta no email
     */
    private void showSuccessMessage() throws AdsException {
        // <user-code id="799647" parentId="799638" hashcode="-6c58f301" length="252">
        ctx.p(ctx.getPreference("RTAUTH.CRIA_CONTA.CREATE_ACCOUNT_SUCCESS", 
                "Enviamos uma mensagem para o seu e-mail. Por favor, siga as instruções contidas neste e-mail para prosseguir com a ativação de sua conta!"));
        getForm().delAction("INSERT");
        // </user-code>
    }
}
